package pers.fulsun.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

/**
 * 进行授权服务器的配置。
 */
@Configuration
@EnableAuthorizationServer // 声明开启 OAuth 授权服务器的功能。
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
//    @Autowired
//    private AuthenticationManager authenticationManager;
//    @Autowired
//    UserDetailsService userDetailsService;
//    @Autowired
//    private PasswordEncoder passwordEncoder;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置使用 AuthenticationManager 实现用户认证的功能 对应在 {@link SecurityConfig#authenticationManagerBean()}
     * 配置使用 userDetailsService 获取用户信息 对应在 {@link SecurityConfig#userDetailsService()}
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//        endpoints.authenticationManager(authenticationManager);
//                .userDetailsService(userDetailsService);
    }

    /**
     * 设置 /oauth/check_token 端点，通过认证后可访问。
     * 这里的认证，指的是使用 client-id + client-secret 进行的客户端认证，不要和用户认证混淆。
     *
     * @param oauthServer
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        // Spring Security OAuth2会公开了两个端点，用于检查令牌（/oauth/check_token和/oauth/token_key），
        // 这些端点默认受保护denyAll()。tokenKeyAccess（）和checkTokenAccess（）方法会打开这些端点以供使用。
        oauthServer.tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()")
                .allowFormAuthenticationForClients();

    }

    /**
     * 进行 Client 客户端的配置。
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //  设置使用基于内存的 Client 存储器。实际情况下，最好放入数据库中，方便管理。
        clients.inMemory()
                // 创建一个 Client 配置。
                // Client 账号、密码
                .withClient("clientapp").secret(passwordEncoder().encode("112233"))
//                .authorizedGrantTypes("password") // 密码模式
//                .authorizedGrantTypes("authorization_code") // 授权码模式
//                .authorizedGrantTypes("implicit") // 简化模式
                .authorizedGrantTypes("client_credentials") // 客户端模式
                // 可授权的 Scope
                .scopes("read_userinfo", "read_contacts")
        // 如果要继续添加另外的 Client 配置，可以使用 #and() 方法继续拼接。
        // .and().withClient()
        ;
    }
}
